package com.huabo.file;

import com.huabo.file.fastdfs.*;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.InitializingBean;

import java.io.*;
import java.util.Properties;

/**
 * fastDFS组件保存文件
 * Created by Jackie Liu on 2017/4/23.
 */
public class FdfsFileOperation implements FileOperation, InitializingBean {

    private int connectTimeoutInSeconds = 5;
    private int networkTimeoutInSeconds = 30;
    private String charset = "UTF-8";
    private boolean httpAntiStealToken = false;
    private String httpSecretKey = "FastDFSabcd1232334";
    private int httpTrackerHttpPort = 80;
    private String trackerServers;

    private TrackerClient trackerClient;

    private TrackerServer trackerServer;
    private StorageServer storageServer;

    private void closeSocket() {
        try {
            if (storageServer != null) {
                storageServer = null;
                storageServer.close();
            }
            if (trackerServer != null) {
                trackerServer = null;
                trackerServer.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private StorageClient1 getStorageClient() {
        try {
            TrackerServer trackerServer = trackerClient.getConnection();
            StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
            return new StorageClient1(trackerServer, storageServer);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String save(File file) {
        ByteArrayOutputStream bos = null;
        try {
            FileInputStream fis = new FileInputStream(file);
            bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            return getStorageClient().upload_file1(bos.toByteArray(), FilenameUtils.getExtension(file.getName()), null);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (FastDFSException e) {
            e.printStackTrace();
        } finally {
            closeSocket();
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    @Override
    public String save(InputStream is, String logicName) {
        try {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = is.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            bos.close();

            return getStorageClient().upload_file1(bos.toByteArray(), FilenameUtils.getExtension(logicName), null);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (FastDFSException e) {
            e.printStackTrace();
        } finally {
            closeSocket();
        }
        return null;
    }

    @Override
    public byte[] read(String filePath) {
        try {
            return getStorageClient().download_file1(filePath);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (FastDFSException e) {
            e.printStackTrace();
        } finally {
            closeSocket();
        }
        return new byte[0];
    }

    @Override
    public boolean remove(String filePath) {
        try {
            return getStorageClient().delete_file1(filePath) == 0;
        } catch (IOException e) {
            e.printStackTrace();
        } catch (FastDFSException e) {
            e.printStackTrace();
        } finally {
            closeSocket();
        }
        return false;
    }

    @Override
    public void afterPropertiesSet() {
        Properties props = new Properties();
        props.put(ClientGlobal.PROP_KEY_CONNECT_TIMEOUT_IN_SECONDS, connectTimeoutInSeconds);
        props.put(ClientGlobal.PROP_KEY_NETWORK_TIMEOUT_IN_SECONDS, networkTimeoutInSeconds);
        props.put(ClientGlobal.PROP_KEY_CHARSET, charset);
        props.put(ClientGlobal.PROP_KEY_HTTP_ANTI_STEAL_TOKEN, httpAntiStealToken);
        props.put(ClientGlobal.PROP_KEY_HTTP_SECRET_KEY, httpSecretKey);
        props.put(ClientGlobal.PROP_KEY_HTTP_TRACKER_HTTP_PORT, httpTrackerHttpPort);
        props.put(ClientGlobal.PROP_KEY_TRACKER_SERVERS, trackerServers);
        try {
            ClientGlobal.initByProperties(props);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (FastDFSException e) {
            e.printStackTrace();
        }
        trackerClient = new TrackerClient();
    }


    public String getCharset() {
        return charset;
    }

    public void setCharset(String charset) {
        this.charset = charset;
    }

    public int getConnectTimeoutInSeconds() {
        return connectTimeoutInSeconds;
    }

    public void setConnectTimeoutInSeconds(int connectTimeoutInSeconds) {
        this.connectTimeoutInSeconds = connectTimeoutInSeconds;
    }

    public int getNetworkTimeoutInSeconds() {
        return networkTimeoutInSeconds;
    }

    public void setNetworkTimeoutInSeconds(int networkTimeoutInSeconds) {
        this.networkTimeoutInSeconds = networkTimeoutInSeconds;
    }

    public boolean isHttpAntiStealToken() {
        return httpAntiStealToken;
    }

    public void setHttpAntiStealToken(boolean httpAntiStealToken) {
        this.httpAntiStealToken = httpAntiStealToken;
    }

    public String getHttpSecretKey() {
        return httpSecretKey;
    }

    public void setHttpSecretKey(String httpSecretKey) {
        this.httpSecretKey = httpSecretKey;
    }

    public int getHttpTrackerHttpPort() {
        return httpTrackerHttpPort;
    }

    public void setHttpTrackerHttpPort(int httpTrackerHttpPort) {
        this.httpTrackerHttpPort = httpTrackerHttpPort;
    }

    public String getTrackerServers() {
        return trackerServers;
    }

    public void setTrackerServers(String trackerServers) {
        this.trackerServers = trackerServers;
    }
}
